package mtm.ui.job;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;

import mtm.constants.Constants;
import mtm.date.MtmDate;
import mtm.date.MtmMonth;
import mtm.db.DatabaseHandler;
import mtm.db.Job;
import mtm.db.RepeatJob;
import mtm.ui.MainFrame;
import mtm.ui.misc.ColorLabel;
import mtm.ui.misc.EditableComboBox;
import mtm.ui.misc.TimeComboBox;
import mtm.ui.misc.ColorLabel.MouseClickedListener;
import mtm.ui.panel.MonthPanel;
import mtm.ui.panel.WeekPanel;

import com.toedter.calendar.JDateChooser;

public class RepeatJobFrame extends JFrame {
	
private DatabaseHandler handler = DatabaseHandler.getInstance();
	
	private JLabel lblName;
	private JLabel lblRange;
	private JLabel lblTime;
	private JLabel lblRepeat;
	private JLabel lblColor;
	private JLabel lblDescription;
	
	private JTextField txtName;
	private JDateChooser startDateChooser;
	private JDateChooser dueDateChooser;
	private TimeComboBox cbFromTime;
	private TimeComboBox cbToTime;
	private JTextField txtElapse;
	private EditableComboBox cbPause;
	private JTextArea taDescription;
	
	private JButton btnOk;
	private JButton btnCancel;

	private JPanel namePanel;
	private JPanel datePanel;
	private JPanel timePanel;
	private JPanel repeatPanel;
	private JPanel colorPanel;
	private JPanel descriptionPanel;
	
	
	/**
	 * Constructor
	 * @param startDate
	 * @param dueDate
	 */
	public RepeatJobFrame(MtmDate startDate, MtmDate dueDate) {
		this();
		
		// init start date and due date
		startDateChooser.setDate(startDate.getDayFormat());
		dueDateChooser.setDate(dueDate.getDayFormat());
		// init elapse date
		txtElapse.setText( "" + (1 + dueDate.getDate() - startDate.getDate()) );
	}
	
	
	/**
	 * Constructor
	 * @param job
	 */
	public RepeatJobFrame(Job job) {
		this();
		
		// init some fields
		txtName.setText(job.getJobName());
		if (job.getStartTime() != null) {
			startDateChooser.setDate(job.getStartTime().getDayFormat());
			cbFromTime.setText(job.getStartTime().getTimeFormat());
		}
		if (job.getEndTime() != null) {
			cbToTime.setText(job.getEndTime().getTimeFormat());
		}
		taDescription.setText(job.getDescription());
		lblColor.setBackground(new Color(job.getColor()));
	}

	
	/**
	 * Constructor
	 */
	private RepeatJobFrame() {
		super("Thiết lập chuỗi công việc");
		
		setUpComponents();
		
		// ok button
		// TODO add job
		btnOk = new JButton("Thêm việc");
		btnOk.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// insert repeat job
				if (isFieldsValid()) {
					insertRepeatJob();
					// close this frame
					dispose();
				} else {
					JOptionPane.showMessageDialog(null, "Thông tin không hợp lệ");
				}
			}
		});
		
		// cancel button
		btnCancel = new JButton("Thoát");
		btnCancel.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// close this frame
				dispose();
			}
		});
		
		setLayoutAndGUI();
	}
	
	
	/**
	 * Constructor
	 * @param job the repeat job to display and modify
	 */
	public RepeatJobFrame(RepeatJob job) {
		super("Chỉnh sửa chuỗi công việc");
		
		// set up components
		setUpComponents();
		
		// fill informations
		txtName.setText(job.getJobName());
		startDateChooser.setDate(job.getStartTime().getDayFormat());
		if (job.getDueTime() != null) {
			dueDateChooser.setDate(job.getDueTime().getDayFormat());
		}
		cbFromTime.setText(job.getStartTime().getTimeFormat());
		cbToTime.setText(job.getEndTime().getTimeFormat());
		txtElapse.setText(job.getElapse() + "");
		switch (job.getPause()) {
		case RepeatJob.DATE_LOOP:
			cbPause.setSelectedIndex(0);
			break;
			
		case RepeatJob.WEEK_LOOP:
			cbPause.setSelectedIndex(1);
			break;
			
		case RepeatJob.MONTH_LOOP:
			cbPause.setSelectedIndex(2);
			break;
			
		case RepeatJob.YEAR_LOOP:
			cbPause.setSelectedIndex(3);
			break;
			
		default:
			cbPause.setText(job.getPause() + "");
			break;
		}
		taDescription.setText(job.getDescription());
		lblColor.setBackground(new Color(job.getColor()));
		
		// ok button
		// TODO update job
		btnOk = new JButton("Cập nhật");
		final int jobId = job.getId();
		btnOk.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if (isFieldsValid()) {
					// update in DB
					handler.updateRepeatJob(getCurrentJob(), jobId);
					
					// update UI
					if (MainFrame.getInstance().isWeekView()) {
						WeekPanel.getInstance().reloadJobs();
					} else {
						MonthPanel.getInstance().reloadJobs();
					}
					
					// close RepeatJobFrame
					dispose();
				} else {
					JOptionPane.showMessageDialog(null, "Thông tin không hợp lệ");
				}
				
			}
		});
		
		// cancel button
		btnCancel = new JButton("Xóa");
		btnCancel.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				int deleteRepeatJobConfirm = JOptionPane.showConfirmDialog(null, "Đây là một chuỗi công việc, bạn có muốn xóa tất cả chuỗi công việc");
				if (deleteRepeatJobConfirm == JOptionPane.OK_OPTION) {
					// delete in DB
					handler.removeRepeatJob(jobId);
					
					// delete in WeekPanel
					if (MainFrame.getInstance().isWeekView()) {
						WeekPanel.getInstance().removeRepeatJob(jobId);
					} 
					// delete in MonthPanel
					else {
						MonthPanel.getInstance().removeRepeatJob(jobId);
					}
				}
				
				// close this frame
				dispose();
			}
		});
		
		// set layout and GUI
		setLayoutAndGUI();
	}
	
	
	/**
	 * Set up components in this frame and layout them
	 */
	private void setUpComponents() {
		/*
		 *  labels
		 */
		lblName = new JLabel("Tên việc");
		lblRange = new JLabel("Ngày");
		lblRange.setToolTipText("Ngày bắt đầu và ngày kết thúc của chuỗi công việc");
		lblTime = new JLabel("Thời gian");
		lblTime.setToolTipText("Thời gian làm việc trong 1 ngày");
		lblRepeat = new JLabel("Lặp lại");
		lblRepeat.setToolTipText("Cách thức lặp lại của công việc");
		lblColor = new JLabel("Màu đại diện");
		lblColor.setOpaque(true);
		lblColor.setToolTipText("Màu sắc thể hiện cho công việc lúc hiển thị trên lịch");
		lblDescription = new JLabel("Ghi chú");
		
		
		/*
		 *  fields
		 */
		// job name
		namePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		txtName = new JTextField(20);	
		txtName.setBorder(new LineBorder(Color.red, 2, true));
		namePanel.add(txtName);
		
		// range time of job specified by date chooser
		datePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		startDateChooser = new JDateChooser();
		startDateChooser.setLocale(new Locale("vi"));
		dueDateChooser = new JDateChooser();
		dueDateChooser.setLocale(new Locale("vi"));
		
		datePanel.add(new JLabel("Từ ngày "));
		datePanel.add(startDateChooser);
		datePanel.add(new JLabel(" tới ngày"));
		datePanel.add(dueDateChooser);
		
		// time panel
		timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		cbFromTime = new TimeComboBox();
		cbToTime = new TimeComboBox();
		
		timePanel.add(cbFromTime);
		timePanel.add(new JLabel("tới"));
		timePanel.add(cbToTime);
		
		// repeat panel
		repeatPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		txtElapse = new JTextField(5);
		txtElapse.setText("1");
		txtElapse.setHorizontalAlignment(JTextField.CENTER);
		cbPause = new EditableComboBox(Constants.REPEAT_JOB_PAUSE_TYPE);
		
		repeatPanel.add(new JLabel("Liên tiếp trong"));
		repeatPanel.add(txtElapse);
		repeatPanel.add(new JLabel("ngày         Lặp lại theo(ngày)"));
		repeatPanel.add(cbPause);
		
		// color chooser
		colorPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		for (final ColorLabel lbl : ColorLabel.JOB_COLOR_LABEL) {
			lbl.setMouseClickedListener(new MouseClickedListener() {
				
				@Override
				public void onMouseClicked() {
					lblColor.setBackground(new Color(lbl.getRGB()));
				}
			});
			colorPanel.add(lbl);
		}
		
		// description
		descriptionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		taDescription = new JTextArea(2, 30);
		taDescription.setToolTipText("Đừng ghi chú dài quá ^^");
		taDescription.setBorder(new LineBorder(Color.green, 2, true));
		descriptionPanel.add(taDescription);
	}
	
	
	/**
	 * Set layout and GUI 
	 */
	private void setLayoutAndGUI() {
		
		/*
		 *  set layout
		 */
		JPanel labelPanel = new JPanel();
		labelPanel.setLayout(new GridLayout(6, 1));
		labelPanel.add(lblName);
		labelPanel.add(lblRange);
		labelPanel.add(lblTime);
		labelPanel.add(lblRepeat);
		labelPanel.add(lblColor);
		labelPanel.add(lblDescription);
		
		JPanel fieldPanel = new JPanel();
		fieldPanel.setLayout(new GridLayout(6, 1));
		fieldPanel.add(namePanel);
		fieldPanel.add(datePanel);
		fieldPanel.add(timePanel);
		fieldPanel.add(repeatPanel);
		fieldPanel.add(colorPanel);
		fieldPanel.add(descriptionPanel);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		buttonPanel.add(btnOk);
		buttonPanel.add(btnCancel);
		
		setLayout(new BorderLayout());
		add(labelPanel, BorderLayout.WEST);
		add(fieldPanel, BorderLayout.CENTER);
		add(buttonPanel, BorderLayout.SOUTH);
		
		
		/*
		 *  show GUI
		 */
		setResizable(false);
		setVisible(true);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		pack();
		setLocationRelativeTo(null);
	}
	
	
	/**
	 * Validate fields of frame before insert to DB
	 */
	private boolean isFieldsValid() {
		// no empty job name
		if (txtName.getText().trim().equals("")) {
			return false;
		}
		
		// start time must smaller than end time
		if (cbFromTime.getSelectedIndex() >= cbToTime.getSelectedIndex()) {
			return false;
		}
		
		// start date must not null
		if (startDateChooser.getDate() == null) {
			return false;
		}
		
		// start date must smaller than due date
		if (dueDateChooser.getDate() != null) {
			if (startDateChooser.getDate().compareTo(dueDateChooser.getDate()) > 0) {
				return false;
			}
		}
		
		// check for integer input int elapse text
		try {
			int elapse = Integer.parseInt(txtElapse.getText());
			if (elapse < 0) {
				return false;
			}
		} catch (NumberFormatException ex) {
			return false;
		}
		// check for elapse time must smaller than pause time
		int elapse = Integer.parseInt(txtElapse.getText());
		int pause;
		RepeatJob job = getCurrentJob();
		MtmMonth month = new MtmMonth(job.getStartTime().getMonth(), job.getStartTime().getDate());
		switch (cbPause.getSelectedIndex()) {
		case 0:
			pause = 1;
			break;
			
		case 1:
			pause = 7;
			break;
			
		case 2:
			pause = month.getNumberOfDays();
			break;
			
		case 3:
			pause = month.getNumberOfDaysInYear();
			break;
			
		default:
			pause = Integer.parseInt(cbPause.getText());
			break;
		}
		
		// in case pause = 1 we accept this input
		if (pause != 1 && elapse > pause) {
			return false;
		}
		
		return true;
	}
	
	
	/**
	 * The current job is display in frame
	 * @return
	 */
	private RepeatJob getCurrentJob() {
		RepeatJob job = new RepeatJob();
		
		// job name
		job.setJobName(txtName.getText());
		// start time
		job.setStartTime(MtmDate.createFromDateAndTime( startDateChooser.getDate(), (String) cbFromTime.getSelectedItem()) );
		// end time
		job.setEndTime(MtmDate.createFromDateAndTime( startDateChooser.getDate(), (String) cbToTime.getSelectedItem()) );
		// due time
		if (dueDateChooser.getDate() != null) {
			job.setDueTime(new MtmDate(dueDateChooser.getDate()));
		}
		// elapse date
		job.setElapse(Integer.parseInt(txtElapse.getText()));
		// pause date
		if (cbPause.isIntegerInput()) {
			job.setPause(Integer.parseInt(cbPause.getText()));
		} else {
			switch (cbPause.getSelectedIndex()) {
			case 0:
				job.setPause(RepeatJob.DATE_LOOP);
				break;
				
			case 1:
				job.setPause(RepeatJob.WEEK_LOOP);
				break;
				
			case 2:
				job.setPause(RepeatJob.MONTH_LOOP);
				break;
				
			case 3:
				job.setPause(RepeatJob.YEAR_LOOP);
				break;
			}
		}
		// color
		int currentRGB= lblColor.getBackground().getRGB();
		boolean isDefaultColor = true;
		for (ColorLabel lbl : ColorLabel.JOB_COLOR_LABEL) {
			if (currentRGB == lbl.getRGB()) {
				isDefaultColor = false;
				break;
			}
		}
		if (isDefaultColor) {
			 job.setColor(Constants.DEFAULT_JOB_COLOR);
		} else {
			job.setColor(lblColor.getBackground().getRGB());
		}
		// description
		job.setDescription(taDescription.getText());
		
		return job;
	}


	/**
	 * Insert a repeat job to DB 
	 */
	private void insertRepeatJob() {
		if (isFieldsValid()) {
			// insert in DB
			handler.insertRepeatJob(getCurrentJob());
			
			// insert in UI
			if (MainFrame.getInstance().isWeekView()) {
				WeekPanel.getInstance().reloadJobs();
			} else {
				MonthPanel.getInstance().reloadJobs();
			}
		}
	}

}
